from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdfparser import PDFParser
import os
import json

def generate_html_outline(pdf_path, output_html):
    with open(pdf_path, "rb") as f:
        parser = PDFParser(f)
        doc = PDFDocument(parser)
        outlines = list(doc.get_outlines())  # Convert generator to list

        # Convert outlines to JSON format and track which items have children
        outline_data = []
        has_children = set()  # Track which items have children
        
        for i, entry in enumerate(outlines):
            level, title, dest, *_ = entry
            if level <= 3:  # Only include levels 1-3
                outline_data.append({
                    "level": level,
                    "title": title
                })
                # Check if this item has children
                if i < len(outlines) - 1 and outlines[i + 1][0] > level:
                    has_children.add(len(outline_data) - 1)

        # Start HTML content
        html_content = """
        <!DOCTYPE html>
        <html>
        <head>
            <title>PDF Outline</title>
            <style>
                * {
                    margin: 0;
                    padding: 0;
                    box-sizing: border-box;
                }
                body {
                    font-family: Arial, sans-serif;
                    margin: 20px;
                    line-height: 1.5;
                }
                .tree {
                    list-style: none;
                }
                .tree ul {
                    list-style: none;
                    padding-left: 20px;
                }
                .tree li {
                    margin: 5px 0;
                }
                .level1 {
                    font-size: 18px;
                    font-weight: bold;
                }
                .level2 {
                    font-size: 16px;
                }
                .level3 {
                    font-size: 14px;
                }
                .toggle {
                    cursor: pointer;
                    user-select: none;
                }
                .toggle::before {
                    content: "▶";
                    display: inline-block;
                    margin-right: 6px;
                    transition: transform 0.2s;
                }
                .toggle.active::before {
                    transform: rotate(90deg);
                }
                .hidden {
                    display: none;
                }
                .no-children {
                    color: #666;
                }
                .no-children::before {
                    content: "•";
                    display: inline-block;
                    margin-right: 6px;
                    color: #999;
                }
            </style>
        </head>
        <body>
            <h1>PDF Outline</h1>
            <ul id="tree" class="tree"></ul>
            <script>
                const outlineData = """ + json.dumps(outline_data) + """;
                const hasChildren = new Set(""" + json.dumps(list(has_children)) + """);
                
                function createTreeItem(item, index) {
                    const li = document.createElement('li');
                    const span = document.createElement('span');
                    span.textContent = item.title;
                    span.className = `level${item.level}`;
                    
                    if (item.level < 3) {
                        if (hasChildren.has(index)) {
                            span.classList.add('toggle');
                            // Make level 1 items active by default
                            if (item.level === 1) {
                                span.classList.add('active');
                            }
                            span.addEventListener('click', function() {
                                this.classList.toggle('active');
                                const ul = this.nextElementSibling;
                                if (ul) {
                                    ul.classList.toggle('hidden');
                                }
                            });
                        } else {
                            span.classList.add('no-children');
                        }
                    }
                    
                    li.appendChild(span);
                    return li;
                }

                function buildTree(source) {
                    const tree = document.getElementById('tree');
                    const stack = [{element: tree, level: 0}];

                    source.forEach((item, index) => {
                        const li = createTreeItem(item, index);
                        
                        // Find the appropriate parent
                        while (stack.length > 1 && stack[stack.length - 1].level >= item.level) {
                            stack.pop();
                        }
                        
                        const parent = stack[stack.length - 1].element;
                        
                        // If this is a level 2 or 3 item, ensure it's wrapped in a ul
                        if (item.level > 1) {
                            let parentUl = parent.lastElementChild;
                            if (!parentUl || parentUl.tagName !== 'UL') {
                                parentUl = document.createElement('ul');
                                parent.appendChild(parentUl);
                                // Hide level 3 items by default
                                if (item.level === 3) {
                                    parentUl.classList.add('hidden');
                                }
                            }
                            parentUl.appendChild(li);
                        } else {
                            parent.appendChild(li);
                        }
                        
                        // Add to stack if it might have children
                        if (item.level < 3) {
                            stack.push({element: li, level: item.level});
                        }
                    });
                }

                // Initialize the tree
                buildTree(outlineData);
            </script>
        </body>
        </html>
        """

        # Write to HTML file
        with open(output_html, 'w', encoding='utf-8') as html_file:
            html_file.write(html_content)

if __name__ == "__main__":
    pdf_path = "/Users/wu/Desktop/复习/java-fuxi.pdf"
    output_html = "pdf_outline.html"
    generate_html_outline(pdf_path, output_html)
    print(f"HTML file generated: {os.path.abspath(output_html)}") 